package simuladores;

import java.math.BigDecimal;
import java.math.RoundingMode;

import util.Operacao;
import util.Real;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import custos.CalculadorDeCusto;
import custos.ImpostoDeRenda;

/**
 * Simula as operacos de compra e venda de um ativo
 * 
 * @author pisaruk
 * 
 */
public class SimulacaoEnumerativa {
	private Real precoCompra;

	private Real precoCompraReal;

	private BigDecimal quantidadeVendida;

	private CalculadorDeCusto calculadorDeCusto;

	private Real investimentoInicial;

	private BigDecimal variacao;

	private Real precoVenda;

	private Real custoVenda;

	private Real custoCompra;

	private Real lucroBruto;

	private BigDecimal lucroBrutoPercentual;

	private Real lucroLiquido;

	private BigDecimal lucroLiquidoPercentual;

	private Real impostos;

	private Real custoTotal;

	private Real retornoFinalBruto;

	private Real retornoFinalLiquido;

	private BigDecimal quantidadeComprada;

	/**
	 * 
	 * @param precoCompra
	 * @param precoVenda
	 * @param quantidadeComprada
	 * @param quantidadeVendida
	 * @param custoCompra
	 * @param investimentoInicial
	 * @param calculadorDeCusto
	 */
	public SimulacaoEnumerativa(Real precoCompra, Real precoVenda,
			BigDecimal quantidadeComprada, BigDecimal quantidadeVendida,
			Real custoCompra, Real investimentoInicial,
			CalculadorDeCusto calculadorDeCusto) {
		this.calculadorDeCusto = calculadorDeCusto;
		this.precoCompra = precoCompra;
		this.precoVenda = precoVenda;
		this.quantidadeComprada = quantidadeComprada;
		this.quantidadeVendida = quantidadeVendida;
		this.custoCompra = custoCompra;
		this.investimentoInicial = investimentoInicial;
		calcular();
	}

	private void calcular() {
		BigDecimal desconto = new BigDecimal(0);
		variacao = precoVenda.getValor().divide(precoCompra.getValor(), 4,
				RoundingMode.DOWN).subtract(new BigDecimal("1.00")).multiply(
				new BigDecimal("100.00")).setScale(2, RoundingMode.DOWN);
		precoCompraReal = investimentoInicial.divide(quantidadeComprada);
		custoVenda = calculadorDeCusto.calcular(quantidadeVendida, precoVenda,
				Operacao.operacaoFinal, desconto);
		lucroBruto = precoVenda.multiply(quantidadeVendida).subtract(
				investimentoInicial.add(custoVenda));
		lucroBrutoPercentual = new BigDecimal(100).multiply(
				lucroBruto.getValor().divide(investimentoInicial.getValor(), 4,
						RoundingMode.DOWN)).setScale(2);
		lucroLiquido = lucroBruto.subtract(ImpostoDeRenda.calcular(lucroBruto,
				Operacao.operacaoFinal));
		lucroLiquidoPercentual = lucroLiquido.getValor().divide(
				investimentoInicial.getValor(), 4, RoundingMode.DOWN).multiply(
				new BigDecimal(100)).setScale(2, RoundingMode.DOWN);
		custoTotal = custoVenda.add(custoCompra);
		retornoFinalBruto = investimentoInicial.add(lucroBruto);
		retornoFinalLiquido = investimentoInicial.add(lucroLiquido);
	}

	public String toString() {
		XStream xstream = new XStream(new DomDriver());
		xstream.alias(getClass().getName().substring(
				getClass().getPackage().getName().length() + 1), getClass());
		return xstream.toXML(this);
	}

	public Real getCustoVenda() {
		return custoVenda;
	}

	public Real getLucroBruto() {
		return lucroBruto;
	}

	public BigDecimal getLucroBrutoPercentual() {
		return lucroBrutoPercentual;
	}

	public Real getLucroLiquido() {
		return lucroLiquido;
	}

	public BigDecimal getLucroLiquidoPercentual() {
		return lucroLiquidoPercentual;
	}

	public Real getImpostos() {
		return impostos;
	}

	public Real getCustoTotal() {
		return custoTotal;
	}

	public BigDecimal getVariacao() {
		return variacao;
	}

	public Real getRetornoFinalBruto() {
		return retornoFinalBruto;
	}

	public Real getRetornoFinalLiquido() {
		return retornoFinalLiquido;
	}

	public Real getPrecoVenda() {
		return precoVenda;
	}

	public Real getPrecoCompraReal() {
		return precoCompraReal;
	}

}